package com.sugon.api;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.annotation.AuthCheck;
import com.sugon.annotation.AutoLog;
import com.sugon.annotation.LoginUser;
import com.sugon.dao.DevMaintenanceTicketItemDao;
import com.sugon.entity.ApiResult;
import com.sugon.entity.DevMaintenanceTicketEntity;
import com.sugon.entity.DevMaintenanceTicketItemEntity;
import com.sugon.entity.SysUserEntity;
import com.sugon.entity.dto.HandleDevMaintenanceOptionParam;
import com.sugon.modules.analyse.model.chart.PieChartOptionDataVO;
import com.sugon.modules.analyse.service.IDeviceAnalyseService;
import com.sugon.modules.base.consts.BusModule;
import com.sugon.modules.device.consts.DevMaintenanceItemExecuteStatus;
import com.sugon.modules.device.consts.DevMaintenanceTicketStatus;
import com.sugon.modules.device.model.vo.DevMaintenanceDelayApplyParam;
import com.sugon.modules.device.model.vo.DevMaintenanceTicketItemDetailVO;
import com.sugon.modules.device.model.vo.DevMaintenanceTicketVO;
import com.sugon.modules.device.service.IDeviceMaintenanceManager;
import com.sugon.modules.device.service.IDeviceMaintenanceTicketManager;
import com.sugon.modules.sys.consts.SysDeptConst;
import com.sugon.service.DevMaintenanceTicketItemService;
import com.sugon.service.DevMaintenanceTicketService;
import com.sugon.util.ApiBaseAction;
import com.sugon.util.ApiPageUtils;
import com.sugon.utils.Query;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 设备维护工单API,目前支持一下功能
 * 1、获取当前周可以执行的分派给我的处于可工作期的工单，支持根据设备编码查询
 * 2、获取维护工单项
 * 3、批量完成设备维护项
 * 4、延期申请
 * 5、添加异常记录
 */
@Api(tags = "维护工单接口")
@RestController
@RequestMapping("/api/v1/device/maintenance")
public class DeviceMaintenanceApiController extends ApiBaseAction {

    @Autowired
    private DevMaintenanceTicketService devMaintenanceTicketService;
    @Autowired
    private DevMaintenanceTicketItemService devMaintenanceTicketItemService;
    @Autowired
    private DevMaintenanceTicketItemDao devMaintenanceTicketItemDao;
    @Autowired
    private IDeviceMaintenanceManager deviceMaintenanceManager;
    @Autowired
    private IDeviceMaintenanceTicketManager deviceMaintenanceTicketManager;
    @Autowired
    private IDeviceAnalyseService deviceAnalyseService;

    @AuthCheck
    @ApiOperation(value = "获取设备维护工单统计报表API")
    @ApiImplicitParam(name = "statType", value = "统计类别，本周还是本月", paramType = "query", dataType = "string", required = true, allowableValues = "WEEKLY,MONTHLY")
    @PostMapping("/stat")
    public ApiResult<PieChartOptionDataVO> loadDevMaintenanceTicketStat(@ApiIgnore @LoginUser SysUserEntity loginUser, @RequestParam String statType) {
        ApiResult<PieChartOptionDataVO> apiResult = new ApiResult<>();
        // 校验是否合法的统计类别
        if (!StrUtil.equalsAny(statType, "WEEKLY", "MONTHLY")) {
            return apiResult.failMsg("非法统计类别！");
        }
        // 车间看车间，制造处看整体
        String workShopId = loginUser.getWorkShopId();
        if (SysDeptConst.ZZC_CODE.equals(workShopId)) {
            workShopId = null;
        }
        return apiResult.success(deviceAnalyseService.loadDevMaintenanceTicketStat(statType, workShopId));
    }

    @AutoLog(value = "移动端查看PM工单列表", busModule = BusModule.DEVICE_MAINTENANCE)
    @AuthCheck
    @ApiOperation(value = "维护工单列表API", notes = "领导可以看本周所有的维护工单，维修工只看分配给自己的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "当前页码", paramType = "query", dataType = "int", required = true),
            @ApiImplicitParam(name = "limit", value = "每页记录数", paramType = "query", dataType = "int", required = true)
    })
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    public Object getMaintainPlanList(@ApiIgnore @LoginUser SysUserEntity loginUser, @ApiIgnore @RequestParam Map<String, Object> params) {
        ApiResult<ApiPageUtils> apiResult = new ApiResult<>();
        /*
            如果传递日期，那么查询日期所在周的
            如果不传，那么查询本月的
         */
        Date startDate = MapUtil.getDate(params, "startDate");
        if (startDate != null) {
            params.put("weekOfYear", DateUtil.weekOfYear(startDate));
        } else {
            DateTime current = DateUtil.date();
            params.put("startTime", DateUtil.formatDateTime(DateUtil.beginOfMonth(current)));
            /*
                默认显示当月维护工单， 如果月末这一天所在的周末跨月了。
                那么需要将统计的截止时间推迟到周末
             */
            Date endTime = DateUtil.endOfMonth(current);
            Date endOfWeek = DateUtil.endOfWeek(endTime);
            if (DateUtil.month(endTime) + 1 == DateUtil.month(endOfWeek)) {
                endTime = endOfWeek;
            }
            params.put("endTime", DateUtil.formatDateTime(endTime));
        }
        /*
            设备工程处看所有
            各车间人员看自己车间的
         */
        if (StrUtil.isNotEmpty(loginUser.getDeptCode()) && !StrUtil.equals(loginUser.getDeptCode(), SysDeptConst.ZZC_CODE)) {
            if (loginUser.getLeader() != 1) {
                params.put("executor", loginUser.getUserId());
            } else {
                params.put("deptCode", loginUser.getDeptCode());
            }
        }

        // 执行查询
        Query query = new Query(params);
        List<DevMaintenanceTicketVO> devPlanGcList = devMaintenanceTicketService.queryAllForMobile(query);
        int total = devMaintenanceTicketService.queryAllTotalForMobile(query);
        ApiPageUtils pageUtil = new ApiPageUtils(devPlanGcList, total, query.getLimit(), query.getPage());
        return apiResult.success(pageUtil);
    }

    @AutoLog(value = "移动端查看PM工单详情", busModule = BusModule.DEVICE_MAINTENANCE)
    @AuthCheck
    @ApiOperation(value = "维护工单详情查询API")
    @ApiImplicitParam(name = "id", value = "id", paramType = "query", dataType = "string", required = true)
    @RequestMapping(value = "/detail", method = RequestMethod.POST)
    public ApiResult<List<DevMaintenanceTicketItemDetailVO>> getDetailById(@RequestParam String id) {
        ApiResult<List<DevMaintenanceTicketItemDetailVO>> apiResult = new ApiResult<>();
        Map<String, Object> param = new HashMap<>(1);
        param.put("devMainTicketId", id);
        return apiResult.success(devMaintenanceTicketItemDao.queryAll(param));
    }

    @AutoLog(value = "移动端完成PM工单项", busModule = BusModule.DEVICE_MAINTENANCE)
    @AuthCheck
    @ApiOperation(value = "设备维护工单项完成API")
    @RequestMapping(value = "/complete", method = RequestMethod.POST)
    public ApiResult<String> saveDevMaintainWork(@ApiIgnore @LoginUser SysUserEntity loginUser, @Validated @RequestBody HandleDevMaintenanceOptionParam param, BindingResult bindingResult) {
        // 常规校验
        ApiResult<String> apiResult = getValidApiResult(bindingResult);
        if (apiResult != null) {
            return apiResult;
        }
        apiResult = new ApiResult<>();
        // 校验设备维护项是否存在
        DevMaintenanceTicketItemEntity devPmTicketItem = devMaintenanceTicketItemService.queryObject(param.getDevMaintenanceOptionId());
        if (devPmTicketItem == null) {
            return apiResult.failMsg("设备维护项不存在!");
        }
        // 只能完成本周内开始维护的工单，不得提前开始工作
        DevMaintenanceTicketEntity devPmTicket = devMaintenanceTicketService.queryObject(devPmTicketItem.getDevMainTicketId());
        Assert.notNull(devPmTicket);
        if (DateUtil.weekOfYear(devPmTicket.getStartTime()) > DateUtil.weekOfYear(DateUtil.date())) {
            return apiResult.failMsg("只能完成本周内开始维护的工单，不得提前开始！");
        }
        // 校验是否已完成
        Integer status = devPmTicketItem.getStatus();
        if (NumberUtil.equals(status, DevMaintenanceItemExecuteStatus.DELAY_ED) || NumberUtil.equals(status, DevMaintenanceItemExecuteStatus.ED)) {
            return apiResult.failMsg("当前维护项目已完成!");
        }
        // 设置是否有异常
        devPmTicketItem.setCheckResult(param.getCheckResult());
        devPmTicketItem.setImplementerId(loginUser.getUserId());
        devPmTicketItem.setLiveImageList(param.getLiveImageList());
        return deviceMaintenanceManager.completeDevMaintenanceOption(devPmTicketItem) ? apiResult.success() : apiResult.fail();
    }

    @AutoLog(value = "移动端申请延期PM工单", busModule = BusModule.DEVICE_MAINTENANCE)
    @AuthCheck
    @ApiOperation(value = "申请延期API")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ticketId", value = "维护工单ID", paramType = "body", dataType = "String", required = true),
            @ApiImplicitParam(name = "changeTime", value = "延期时间，格式：yyyy-MM-dd", paramType = "body", dataType = "String", required = true),
            @ApiImplicitParam(name = "item", value = "变更事项", paramType = "body", dataType = "String", required = true),
            @ApiImplicitParam(name = "reason", value = "变更原因", paramType = "body", dataType = "String", required = true)
    })
    @PostMapping("/applyDelay")
    public ApiResult<String> applyDelay(@ApiIgnore @LoginUser SysUserEntity loginUser, @RequestBody @Validated DevMaintenanceDelayApplyParam delayApplyParam, BindingResult bindingResult) {
        // 常规校验
        ApiResult<String> apiResult = getValidApiResult(bindingResult);
        if (apiResult != null) {
            return apiResult;
        }
        apiResult = new ApiResult<>();
        // 1、校验工单是否存在以及是否完成
        DevMaintenanceTicketEntity ticket = devMaintenanceTicketService.queryObject(delayApplyParam.getTicketId());
        if (ticket == null) {
            return apiResult.failMsg("设备维护工单不存在，请确认！");
        }
        // 延期申请中的不允许申请
        if (DevMaintenanceTicketStatus.DELAY_APPLYING.equals(ticket.getStatus())) {
            return apiResult.failMsg("工单延期申请中，请耐心等待！");
        }
        // 已完成、已关闭、已延期完成的工单不允许延期
        List<Integer> temStatusList = CollectionUtil.newArrayList(DevMaintenanceTicketStatus.COMPLETE, DevMaintenanceTicketStatus.STOP, DevMaintenanceTicketStatus.DELAY_COMPLETE);
        if (temStatusList.contains(ticket.getStatus())) {
            return apiResult.failMsg("工单已完成或已关闭，不允许申请延期！");
        }
        // 只可以延期申请自己负责的工单
        if (ticket.getExecutor() == null || !StrUtil.contains(ticket.getExecutor(), loginUser.getUserId())) {
            return apiResult.failMsg("只可以申请延期自己负责的设备维护工单！");
        }
        // 期望延期时间不得早于工单最晚结束时间
        if (delayApplyParam.getChangeTime().before(ticket.getFinalEndTime())) {
            return apiResult.failMsg("期望延期时间不得早于工单结束时间！");
        }
        delayApplyParam.setApplier(loginUser.getUserId());
        delayApplyParam.setDevMaintenanceTicket(ticket);
        return deviceMaintenanceTicketManager.applyChange(delayApplyParam) ? apiResult.success() : apiResult.fail();
    }

}
